package com.woniuxy.kaer.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.kaer.commons.util.Data;
import com.woniuxy.kaer.commons.util.OSSUtil;
import com.woniuxy.kaer.commons.util.PageInfo;
import com.woniuxy.kaer.dto.CollectProductDTO;
import com.woniuxy.kaer.dto.ShoppingCarDTO;
import com.woniuxy.kaer.form.PageForm;
import com.woniuxy.kaer.param.AddProductParam;
import com.woniuxy.kaer.param.AddShoppingParam;
import com.woniuxy.kaer.param.PageParam;
import com.woniuxy.kaer.param.SearchProductParam;
import com.woniuxy.kaer.redis.util.RedisKey;
import com.woniuxy.kaer.shop.model.Product;
import com.woniuxy.kaer.shop.mapper.ProductMapper;
import com.woniuxy.kaer.shop.service.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 郭建东
 * @since 2025年02月17日
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Resource
    private  ProductMapper productMapper;

    @Resource
    private OSSUtil ossUtil;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public void addProduct(AddProductParam param) throws Exception {

        if(param==null){
            throw new Exception("商品数据为空");
        }
        if(param.getPrice().compareTo(BigDecimal.ZERO) <= 0){
            throw new Exception("商品价格必须大于0");
        }
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_name",param.getProductName());
        queryWrapper.eq("product_brand",param.getProductBrand());
        queryWrapper.eq("price",param.getPrice());
        //判断商品(相同品牌，名字价格一样）是否存在
        if (productMapper.selectOne(queryWrapper)!=null){
            throw new Exception("该商品已存在");
        }
        //使用工具类将数据从param复制到product
        Product product = BeanUtil.toBean(param, Product.class);

        //库存为0,状态0默认为下架,冻结库存为0
        product.setInventory(0L);
        product.setProductState(Data.PRODUCT_STATE_DOWN);
        product.setFreeze(0L);
        productMapper.insert(product);
    }

    @Override
    public void updateProductState(Integer productId) throws Exception {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productId);
        //判断商品是否存在
        Product product = productMapper.selectOne(queryWrapper);
        if(product==null){
            throw new Exception("商品不存在");
        }
        //修改商品售卖状态
        if(product.getProductState()== Data.PRODUCT_STATE_UP){
            product.setProductState(Data.PRODUCT_STATE_DOWN);
        }else{
            product.setProductState(Data.PRODUCT_STATE_UP);
        }
        productMapper.updateById(product);
    }

    @Override
    public void updateProductPrice(Integer productId, BigDecimal price) throws Exception {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productId);
        //判断商品是否存在
        Product product = productMapper.selectOne(queryWrapper);
        if(product==null){
            throw new Exception("商品不存在");
        }
        if(price.compareTo(BigDecimal.ZERO) <= 0){
            throw new Exception("商品售价必须大于0");
        }
        product.setPrice(price);
        productMapper.updateById(product);
    }

    @Override
    public void updateProductInventory(Integer productId, Long inventory) throws Exception {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productId);
        //判断商品是否存在
        Product product = productMapper.selectOne(queryWrapper);
        if(product==null){
            throw new Exception("商品不存在");
        }
        if(inventory+product.getInventory()<=0){
            throw new Exception("商品库存必须大于等于0");
        }
        product.setInventory(inventory);
        productMapper.updateById(product);
    }

    @Override
    public PageInfo searchProductByKeyword(SearchProductParam param) throws Exception {
        if(param.getPageNum()==null || param.getPageNum()==0){
            throw new Exception("页码不能为空");
        }
        if(param.getPageSize()==null || param.getPageSize()==0){
            throw new Exception("每页数量不能为空");
        }
        Page<Product> page = new Page<>(param.getPageNum(), param.getPageSize());

        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        //判断关键字是否为空或者为空字符串,拼接查询条件
        if(param.getKeyword()!=null && !param.getKeyword().isEmpty()){
            queryWrapper.like("product_name",param.getKeyword())
                    .or().like("product_brand",param.getKeyword());
        }

        Page<Product> productPage = productMapper.selectPage(page, queryWrapper);

        PageInfo productPageInfo = new PageInfo(productPage);

        return productPageInfo;
    }

    @Override
    public void productCollect(Integer productId, Integer userId) throws Exception {
        Product product = productMapper.selectById(productId);
        //判断商品是否存在
        if(product==null){
            throw new Exception("商品不存在");
        }
        //判断商品是否下架
        if(product.getProductState()== Data.PRODUCT_STATE_DOWN){
            throw new Exception("商品已下架");
        }
        //判断用户是否已经收藏过该商品
        Double score = stringRedisTemplate.opsForZSet().score(RedisKey.userCollectList(userId), productId+"");
        if(score!=null){
            throw new Exception("商品已收藏");
        }
        //收藏商品
        //1.将商品Id保存到当前用户的收藏列表中并且以当前的时间戳作为排序值
        stringRedisTemplate.opsForZSet().add(RedisKey.userCollectList(userId),productId.toString(),new Date().getTime());
        //2.将系统中的收藏排行榜中该商品排序值+1
        stringRedisTemplate.opsForZSet().incrementScore(RedisKey.sysCollectRank(),productId.toString(),1);

    }

    @Override
    public void cancelCollect(Integer productId, Integer userId) throws Exception {
        Product product = productMapper.selectById(productId);
        //判断商品是否存在
        if(product==null){
            throw new Exception("商品不存在");
        }
        //判断商品是否下架
        if(product.getProductState()== Data.PRODUCT_STATE_DOWN){
            throw new Exception("商品已下架");
        }
        //判断用户是否已经收藏过该商品
        Double score = stringRedisTemplate.opsForZSet().score(RedisKey.userCollectList(userId), productId+"");
        if(score==null){
            throw new Exception("商品未收藏");
        }
        //该商品的收藏量为1时，取消收藏的同时删除该记录
        if(stringRedisTemplate.opsForZSet().score(RedisKey.sysCollectRank(),productId.toString())==1){
            //删除该商品收藏记录
            stringRedisTemplate.opsForZSet().remove(RedisKey.userCollectList(userId),productId.toString());
            //删除排行榜中该商品的信息
            stringRedisTemplate.opsForZSet().remove(RedisKey.sysCollectRank(),productId.toString());
        }else{

            //删除该商品收藏记录
            stringRedisTemplate.opsForZSet().remove(RedisKey.userCollectList(userId),productId.toString());
            //该商品收藏数-1
            stringRedisTemplate.opsForZSet().incrementScore(RedisKey.sysCollectRank(),productId.toString(),-1);
        }

    }

    @Override
    public void addShoppingCar(AddShoppingParam param, Integer userId) throws Exception {
        Product product = productMapper.selectById(param.getProductId());
        if(product==null){
            throw new Exception("商品不存在");
        }
        if(product.getProductState()== Data.PRODUCT_STATE_DOWN){
            throw new Exception("该商品已下架");
        }
        //判断当前商品是否已经存在于购物车
        if(stringRedisTemplate.opsForZSet().score(RedisKey.userShoppingList(userId), param.getProductId().toString())!=null){
            //购物车中存在该书籍
            Integer score =Integer.parseInt(stringRedisTemplate.opsForHash().get(RedisKey.userShoppingDetail(userId, param.getProductId()), "number").toString()) ;
            System.out.println(score+param.getNumbers());
            if(score+param.getNumbers()>product.getInventory()){
                throw new Exception("库存不足");
            }
            if(score+param.getNumbers()==0){
                stringRedisTemplate.opsForZSet().remove(RedisKey.userShoppingList(userId), param.getProductId().toString());
                stringRedisTemplate.opsForHash().delete(RedisKey.userShoppingDetail(userId, param.getProductId()), "number");
            }else if(score+param.getNumbers()<0){
                throw new Exception("输入数量错误");
            }
            else{
                stringRedisTemplate.opsForHash().increment(RedisKey.userShoppingDetail(userId, param.getProductId()), "number", param.getNumbers());
            }
        }else{
            if(param.getNumbers()>product.getInventory()){
                throw new Exception("库存不足");
            }
            if(param.getNumbers()<=0){
                throw new Exception("添加数量异常");
            }
            stringRedisTemplate.opsForZSet().add(RedisKey.userShoppingList(userId), param.getProductId()+"", new Date().getTime());
            HashMap<Object, Object> map = new HashMap<>();
            map.put("productId",String.valueOf(param.getProductId()));
            map.put("number",String.valueOf(param.getNumbers()));
            stringRedisTemplate.opsForHash().putAll(RedisKey.userShoppingDetail(userId, param.getProductId()), map);
        }
    }

    @Override
    public PageInfo searchCollect(Integer userId, PageForm form) throws Exception {
        if(form.getPageNum()==null || form.getPageNum()==0){
            throw new Exception("页码不能为空");
        }
        if(form.getPageSize()==null || form.getPageSize()==0){
            throw new Exception("页大小不能为空");
        }
        //根据分页数据查询set集合中的起始位置
        Integer start = Integer.parseInt((form.getPageNum()-1)*form.getPageSize()+"");
        //结束位置
        Integer end = Integer.parseInt(form.getPageNum()*form.getPageSize()-1+"");
        Set<String> idList = stringRedisTemplate.opsForZSet().range(RedisKey.userCollectList(userId), start, end);
        //查询总条数
        System.out.println(userId);
        Long total = stringRedisTemplate.opsForZSet().zCard(RedisKey.userCollectList(userId));
        System.out.println(total);
        //计算总页数
        Long pages = total%form.getPageSize()==0?total/form.getPageSize():total/form.getPageSize()+1;
        ArrayList<Product> list = new ArrayList<>();
        for (String id : idList) {
            Product product = productMapper.selectById(id);
            list.add(product);
        }
        PageInfo pageInfo = new PageInfo();
        pageInfo.setList(list);
        pageInfo.setTotal(total);
        pageInfo.setPages(pages);
        return pageInfo;
    }

    @Override
    public List<CollectProductDTO> selectCollectRank() throws Exception {
        //查找排行中前十的商品id集合
        Set<String> idList = stringRedisTemplate.opsForZSet().reverseRange(RedisKey.sysCollectRank(), 0, 9);
        ArrayList<CollectProductDTO> collectProductDTOS = new ArrayList<>();
        for (String productId : idList) {
            Product product = productMapper.selectById(productId);
            CollectProductDTO collectProductDTO = BeanUtil.toBean(product, CollectProductDTO.class);
            Double number = stringRedisTemplate.opsForZSet().score(RedisKey.sysCollectRank(), productId);
            collectProductDTO.setProductCollect(number.intValue());
            collectProductDTOS.add(collectProductDTO);
        }
        return collectProductDTOS;
    }

    @Override
    public PageInfo searchMyShoppingCar(PageParam param, Integer userId) throws Exception {
        if(param.getPageNum()==null || param.getPageNum()==0){
            throw new Exception("页码不能为空");
        }
        if(param.getPageSize()==null || param.getPageSize()==0){
            throw new Exception("页大小不能为空");
        }
        Integer start = Integer.parseInt((param.getPageNum()-1)*param.getPageSize()+"");
        //结束位置
        Integer end = Integer.parseInt(param.getPageNum()*param.getPageSize()-1+"");
        Set<String> idsList = stringRedisTemplate.opsForZSet().reverseRange(RedisKey.userShoppingList(userId), start, end);
        ArrayList<ShoppingCarDTO> list = new ArrayList<>();
        for (String id : idsList){
            Product product = productMapper.selectById(id);
            ShoppingCarDTO dto = BeanUtil.toBean(product, ShoppingCarDTO.class);
            Integer productId=Integer.parseInt(id);
            dto.setNumber(Integer.parseInt(stringRedisTemplate.opsForHash().get(RedisKey.userShoppingDetail(userId, productId), "number").toString()));
            list.add(dto);
        }
        PageInfo pageInfo = new PageInfo();
        Long total =stringRedisTemplate.opsForZSet().size(RedisKey.userShoppingList(userId));
        pageInfo.setTotal(total);
        Long pages = (total%param.getPageSize()==0)?total/param.getPageSize():total/param.getPageSize()+1;
        pageInfo.setPages(pages);
        pageInfo.setList(list);
        return pageInfo;
    }

    @Override
    public String upImage(MultipartFile file) throws Exception {
        //判断上传的文件的真实类型
        //取出上传的文件的前4个字节，其中保存了文件的类型信息
        InputStream is = file.getInputStream();
        byte[] fileHeader=new byte[4];
        is.read(fileHeader);
        //调用API判断文件类型
        if(!(ossUtil.isJpg(fileHeader)||ossUtil.isPng(fileHeader))){
            throw new Exception("文件类型不支持");
        }
        //先获取文件的后缀名
        String suffix = StringUtils.getFilenameExtension(file.getOriginalFilename());
        String prefix= UUID.randomUUID().toString();
        //实现文件上传
        String url = ossUtil.uploadFile(file.getInputStream(), prefix + "." + suffix, "guojiandong");
        return url;
    }
}
